package com.tulink.yichutu.biz;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tulink.yichutu.entity.WxUserEntity;
import com.tulink.yichutu.service.WxUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户缓存业务方法
 *
 * @author wanchaopeng
 */
@Slf4j
@Component
public class UserCacheBiz {
    private static final String userOpenIdCacheKey = "userCaches";

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private WxUserService wxUserService;

    public void addOpenId(String openId, String userId) {
        if(StringUtils.isBlank(openId) || StringUtils.isBlank(userId)) {
            return;
        }
        try {
            redisTemplate.boundHashOps(userOpenIdCacheKey).put(openId, userId);
        } catch (Exception ex) {
            log.error("addOpenId cache error", ex);
        }
    }

    public void delOpenId(String openId) {
        try {
            redisTemplate.boundHashOps(userOpenIdCacheKey).delete(openId);
        } catch (Exception ex) {
            log.error("delOpenId cache error", ex);
        }
    }

    public String getUserId(String openId) {
        try {
            Object obj = redisTemplate.boundHashOps(userOpenIdCacheKey).get(openId);
            if(obj == null) {
                return null;
            }
            return String.valueOf(obj);
        } catch (Exception ex) {
            log.error("getUserId cache error", ex);
        }
        return null;
    }

    public List<String> getAllOpenIds() {
        try {
            Set<Object> keys = redisTemplate.boundHashOps(userOpenIdCacheKey).keys();
            if(keys != null) {
                return keys.stream().map(String::valueOf).collect(Collectors.toList());
            }
        } catch (Exception ex) {
            log.error("getAllOpenIds cache error", ex);
        }
        return new ArrayList<>();
    }

    public Boolean hasOpenId(String openId) {
        if(StringUtils.isBlank(openId)) {
            return false;
        }
        try {
            return redisTemplate.boundHashOps(userOpenIdCacheKey).hasKey(openId);
        } catch (Exception ex) {
            log.error("cache hasOpenId error", ex);
        }
        return false;
    }

    @PostConstruct
    public void initCache() {
        int count = 0;
        int total = 0;
        int pageSize = 500;
        log.info("开始初始化用户缓存...");
        redisTemplate.delete(userOpenIdCacheKey);
        while(count < 10000) {
            Page<WxUserEntity> page = new Page<>(count, pageSize);
            page = wxUserService.page(
                    page,
                    Wrappers.<WxUserEntity>lambdaQuery()
                            .select(WxUserEntity::getOpenId, WxUserEntity::getId)
                            .eq(WxUserEntity::getSubscribe, 1)
                            .groupBy(WxUserEntity::getOpenId, WxUserEntity::getId)
            );
            Map<String, String> openIdMap = new HashMap<>();
            page.getRecords().forEach(p -> openIdMap.put(p.getOpenId(), p.getId()));
            if(openIdMap.size() > 0) {
                redisTemplate.boundHashOps(userOpenIdCacheKey).putAll(openIdMap);
                total += openIdMap.size();
                log.info("已加载用户：{}", total);
            }
            if(page.getRecords().size() < pageSize) {
                break;
            }
            count++;
        }
        log.info("初始化用户缓存完成：{}", total);
    }

}
